home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fritz: All Fritz
/
All Fritz.zip
/
All Fritz
/
FILES
/
DEMO_VGA
/
FRSTM1.LZH
/
GIFSAVE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-03-26
|
8KB
|
260 lines
#include <string.h>
#include <stdio.h>
#include <graph.h>
#include <conio.h>
#include <stdlib.h>
#include "chkpoint.h"
#include "xbit.h"
/* This is code I shamelessly swiped from Bert Tyler's FRACSRC.ARC with
some very minor modifications.
-Mark */
/*
Save-To-Disk Routines (GIF)
The following routines perform the GIF encoding when the 's' key is pressed.
The routines refer to several variables that are declared elsewhere
[colors, xdots, ydots, and 'dacbox'], and rely on external routines to
actually read and write screen pixels [getcolor(x,y) and putcolor(x,y,color)].
(Writing pixels is just stuffed in here as a sort of on-line status report.)
Otherwise, they perform a generic GIF-encoder function.
Note that these routines use small string- and hash-tables, and "flush"
the GIF entries whenever the hash-table gets two-thirds full or the string
table gets full. They also use the GIF encoding technique of limiting the
encoded string length to a specific size, "adding" a string to the hash table
at that point even if a matching string exists ("adding" is in quotes, because
if a matching string exists we can increment the code counter but safely throw
the duplicate string away, saving both string space and a hash table entry).
This results in relatively good speed and small data space, but at the
expense of compression efficiency (filesize). These trade-offs could be
adjusted by modifying the #DEFINEd variables below.
*/
#define MAXTEST 200
#define MAXENTRY 3001 /* a prime number is best, here */
#define MAXSTRING 40000
char numsaves = 0; /* For adjusting 'save-to-disk' filenames */
FILE *out;
unsigned lentest, lastentry, numentries, numrealentries, nextentry;
int clearcode, endcode;
int strlocn[MAXENTRY], entrynum[MAXENTRY];
unsigned char teststring[MAXTEST], codedstrings[MAXSTRING];
unsigned int hashcode;
unsigned char blockcount, block[266];
int startbits, codebits, bytecount, bitcount;
void raster(int code) /* routine to block and output codes */
{
unsigned int icode, i, j;
if (code == 9999) { /* special start-up signal */
bytecount = 0;
bitcount = 0;
for (i = 0; i < 266; i++)
block[i] = 0;
return;
}
icode = code << bitcount; /* update the bit string */
block[bytecount ] |= (icode & 255);
block[bytecount+1] |= ((icode>>8) & 255);
icode = (code>>8) << bitcount;
block[bytecount+2] |= ((icode>>8) & 255);
bitcount += codebits;
while (bitcount >= 8) { /* locate next starting point */
bitcount -= 8;
bytecount++;
}
if (bytecount > 250 || code == endcode) { /* time to write a block */
if (code == endcode)
while (bitcount > 0) { /* if EOF, find the real end */
bitcount -= 8;
bytecount++;
}
i = bytecount;
blockcount = (unsigned char)i;
fwrite(&blockcount,1,1,out); /* write the block */
fwrite(block,i,1,out);
bytecount = 0; /* now re-start the block */
for (j = 0; j < 5; j++) /* (may have leftover bits) */
block[j] = block[j+i];
for (j = 5; j < 266; j++)
block[j] = 0;
}
}
void inittable(void) /* routine to init tables */
{
int i;
raster(clearcode); /* signal that table is initialized */
numentries = 0; /* initialize the table */
numrealentries = 0;
nextentry = 1;
lentest = 0;
codebits = startbits;
codedstrings[0] = 255; /* clear the hash entries */
for (i = 0; i < MAXENTRY; i++)
strlocn[i] = 0;
}
void inittable(void);
void savetodisk(char *filename, int xdots, int ydots, int colors)
{
int i, j, ydot, xdot, color, outcolor1, outcolor2;
unsigned int hashentry, Offset = 0, n, Plane = 0;
unsigned char bitsperpixel, x, far *Scr = (unsigned char far *)0xa0000000;
if ((out=fopen(filename,"wb")) == NULL) {
printf(" ?? Couldn't create file %s \n", filename);
return;
}
bitsperpixel = 0; /* calculate bits / pixel */
for (i = colors; i >= 2; i /= 2 )
bitsperpixel++;
startbits = bitsperpixel+1; /* start coding with this many bits */
if (colors == 2)
startbits++; /* B&W Klooge */
clearcode = 1 << (startbits - 1); /* set clear and end codes */
endcode = clearcode+1;
outcolor1 = 0; /* use these colors to show progress */
outcolor2 = 1; /* (this has nothing to do with GIF) */
if (colors > 2) {
outcolor1 = 2;
outcolor2 = 3;
}
if (numsaves && 1 == 0) { /* reverse the colors on alt saves */
i = outcolor1;
outcolor1 = outcolor2;
outcolor2 = i;
}
fwrite("GIF87a",1,6,out); /* GIF Signature */
fwrite(&xdots,2,1,out); /* screen descriptor */
fwrite(&ydots,2,1,out);
x = (unsigned char)(128 + ((bitsperpixel-1)<<4) + (bitsperpixel-1));
fwrite(&x,1,1,out);
i = 0;
fwrite(&i,1,1,out);
fwrite(&i,1,1,out);
fwrite(GIFColorTable, sizeof(struct _COLOR_GUNS), 256, out);
fwrite(",",1,1,out); /* Image Descriptor */
i = 0;
fwrite(&i,2,1,out);
fwrite(&i,2,1,out);
fwrite(&xdots,2,1,out);
fwrite(&ydots,2,1,out);
i = 0;
fwrite(&i,1,1,out);
bitsperpixel = (unsigned char)(startbits - 1); /* raster data starts here */
fwrite(&bitsperpixel,1,1,out);
codebits = startbits; /* start encoding */
raster(9999); /* initialize the raster routine */
inittable(); /* initialize the LZW tables */
SetATIPlane(Plane);
for (ydot = 0; ydot < ydots; ydot++) { /* scan through the dots */
for (xdot = 0; xdot < xdots; xdot++) {
while(kbhit()) {
if(getch() == 27) {
fclose(out);
return;
}
}
color = Scr[Offset];
Scr[Offset++] ^= 0xff;
if(!Offset)
SetATIPlane(++Plane);
teststring[0] = (unsigned char)(++lentest);
teststring[lentest] = (unsigned char)color;
if (lentest == 1) { /* root entry? */
lastentry = color;
continue;
}
if (lentest == 2) /* init the hash code */
hashcode = 301 * (teststring[1]+1);
hashcode *= (color + lentest); /* update the hash code */
hashentry = ++hashcode % MAXENTRY;
for( i = 0; i < MAXENTRY; i++) {
if (++hashentry >= MAXENTRY) hashentry = 0;
if (memcmp(teststring,
&codedstrings[strlocn[hashentry]],
lentest+1) == 0)
break;
if (strlocn[hashentry] == 0) i = MAXENTRY;
}
/* found an entry and string length isn't too bad */
if (strlocn[hashentry] != 0 && lentest < MAXTEST-3) {
lastentry = entrynum[hashentry];
continue;
}
raster(lastentry); /* write entry */
numentries++; /* act like you added one, anyway */
if (strlocn[hashentry] == 0) { /* add new string, if any */
entrynum[hashentry] = numentries+endcode;
strlocn[hashentry] = nextentry;
memcpy(&codedstrings[nextentry],
teststring,lentest+1);
nextentry += lentest+1;
numrealentries++;
}
teststring[0] = 1; /* reset current entry */
teststring[1] = (unsigned char)color;
lentest = 1;
lastentry = color;
if ((numentries+endcode) == (1<<codebits))
codebits++; /* use longer encoding */
if (numrealentries > (MAXENTRY*2)/3 || /* out of room? */
nextentry > MAXSTRING-MAXTEST-3) {
raster(lastentry); /* flush & restart */
inittable();
}
}
}
raster(lastentry); /* tidy up - dump the last code */
raster(endcode); /* finish the map */
i = 0; /* raster data ends here */
fwrite(&i,1,1,out);
fwrite(";",1,1,out); /* GIF Terminator */
fclose(out);
Offset = 0;
Plane = 0;
SetATIPlane(Plane);
for(j = 0; j < ydots; j++) {
for(i = 0; i < xdots; i++) {
Scr[Offset++] ^= 0xff;
if(!Offset)
SetATIPlane(++Plane);
}
}
}